"""
修仙游戏核心模块
包含游戏的基础数据结构、枚举类型和核心逻辑
"""
from enum import Enum
from dataclasses import dataclass, field
from typing import Dict, List, Optional, Tuple
import random
import json
import os
from pathlib import Path

class Realm(Enum):
    """修仙境界枚举"""
    无 = 0
    练气 = 1
    筑基 = 2
    金丹 = 3
    元婴 = 4
    化神 = 5
    炼虚 = 6
    合体 = 7
    大乘 = 8
    渡劫 = 9
    
    @classmethod
    def from_string(cls, realm_str: str):
        """从字符串转换为境界枚举"""
        for realm in cls:
            if realm.name == realm_str:
                return realm
        return cls.无

class ItemType(Enum):
    """物品类型枚举"""
    功法 = "功法"
    丹药 = "丹药"
    灵石 = "灵石"
    法宝 = "法宝"
    材料 = "材料"
    其他 = "其他"

@dataclass
class Item:
    """物品类"""
    name: str
    item_type: ItemType
    description: str = ""
    value: int = 0
    
@dataclass
class Monster:
    """怪物类"""
    name: str
    level: int
    hp: int
    attack: int
    defense: int
    exp_reward: int
    item_drops: Dict[str, float] = field(default_factory=dict)  # 物品掉落及概率
    
@dataclass
class Player:
    """玩家类"""
    user_id: str
    name: str
    realm: Realm = Realm.无
    exp: int = 0
    hp: int = 100
    max_hp: int = 100
    mp: int = 100
    max_mp: int = 100
    attack: int = 10  # 攻击力
    defense: int = 5  # 防御力
    current_area: str = "清河镇"
    inventory: Dict[str, int] = field(default_factory=dict)
    unlocked_areas: List[str] = field(default_factory=lambda: ["清河镇"])
    
    def add_item(self, item_name: str, count: int = 1):
        """添加物品到背包"""
        if item_name in self.inventory:
            self.inventory[item_name] += count
        else:
            self.inventory[item_name] = count
    
    def remove_item(self, item_name: str, count: int = 1) -> bool:
        """从背包移除物品"""
        if item_name not in self.inventory or self.inventory[item_name] < count:
            return False
        self.inventory[item_name] -= count
        if self.inventory[item_name] == 0:
            del self.inventory[item_name]
        return True
    
    def has_item(self, item_name: str, count: int = 1) -> bool:
        """检查是否拥有指定数量的物品"""
        return self.inventory.get(item_name, 0) >= count
    
    def can_enter_area(self, required_realm: Realm) -> bool:
        """检查是否可以进入指定境界要求的区域"""
        return self.realm.value >= required_realm.value
    
    def reset_to_newbie(self):
        """重置为新手状态（死亡惩罚）"""
        self.realm = Realm.无
        self.exp = 0
        self.hp = 100
        self.max_hp = 100
        self.mp = 100
        self.max_mp = 100
        self.attack = 10
        self.defense = 5
        self.current_area = "清河镇"
        self.inventory.clear()
        self.unlocked_areas = ["清河镇"]

@dataclass
class AreaInfo:
    """区域信息类"""
    name: str
    adjacent_areas: List[str]
    realm_requirement: Realm
    unlock_item: Optional[str] = None
    resources: Dict[str, float] = field(default_factory=dict)
    random_events: Dict[str, float] = field(default_factory=dict)
    
@dataclass
class GameEvent:
    """游戏事件类"""
    name: str
    description: str
    probability: float
    effects: Dict[str, any] = field(default_factory=dict)

class GameCore:
    """游戏核心类"""
    
    def __init__(self, data_dir: str = "."):
        """初始化游戏核心"""
        self.data_dir = Path(data_dir)
        self.players: Dict[str, Player] = {}
        self.areas: Dict[str, AreaInfo] = {}
        self.items: Dict[str, Item] = {}
        self.events: Dict[str, GameEvent] = {}
        self.monsters: Dict[str, List[Monster]] = {}  # 按区域分类的怪物
        
        # 初始化游戏数据
        self._init_items()
        self._load_map_config()
        self._init_events()
        self._init_monsters()
        
        # 加载玩家数据
        self.load_player_data()
    
    def _init_items(self):
        """初始化物品数据"""
        items_data = [
            ("入门功法残页", ItemType.功法, "残破的功法秘籍，记录着基础修炼方法", 10),
            ("低阶灵石", ItemType.灵石, "蕴含微弱灵气的石头", 5),
            ("中阶灵石", ItemType.灵石, "蕴含中等灵气的石头", 25),
            ("高阶灵石", ItemType.灵石, "蕴含浓郁灵气的石头", 100),
            ("破损妖丹", ItemType.丹药, "妖兽体内的破损内丹", 15),
            ("完整妖丹", ItemType.丹药, "妖兽体内的完整内丹", 50),
            ("炼丹手册", ItemType.功法, "记录炼丹方法的手册", 80),
            ("蝶翼令牌", ItemType.其他, "灵蝶谷的通行令牌", 1),
            ("精铁剑", ItemType.法宝, "精铁锻造的利剑", 30),
            ("灵泉甘露", ItemType.丹药, "灵泉中的甘露，能恢复法力", 40),
            ("洞府法器", ItemType.法宝, "洞府中的古老法器", 60),
            ("灵石精华", ItemType.材料, "提炼后的灵石精华", 35),
            ("上古符文", ItemType.材料, "刻有上古文字的符文石", 80),
            ("古塔法宝", ItemType.法宝, "古塔中的神秘法宝", 120),
            ("空间灵石", ItemType.材料, "蕴含空间之力的特殊灵石", 90),
            ("仙市灵石", ItemType.灵石, "仙市中流通的特制灵石", 45),
            ("坊市法器", ItemType.法宝, "坊市中的精品法器", 70),
            ("商贾秘闻", ItemType.其他, "记录商贾秘密的卷轴", 20),
            ("虚空精华", ItemType.材料, "虚空中凝聚的精华", 150),
            ("虚空法宝", ItemType.法宝, "虚空中孕育的神秘法宝", 200),
            ("云霄仙石", ItemType.灵石, "云霄宫中的仙石", 180),
            ("九天符箓", ItemType.材料, "九天之上的神秘符箓", 160),
            ("仙宫秘宝", ItemType.法宝, "仙宫中的珍贵秘宝", 250),
            ("九天灵果", ItemType.丹药, "九天云海中的灵果", 200),
            ("云海仙草", ItemType.材料, "云海中生长的仙草", 180),
            ("风灵精华", ItemType.材料, "风之精灵的精华", 160),
            ("时光水晶", ItemType.材料, "蕴含时光之力的水晶", 300),
            ("岁月回响", ItemType.其他, "岁月留下的回响", 250),
            ("混沌精华", ItemType.材料, "混沌初开时的精华", 500),
            ("创世法则", ItemType.其他, "创世时留下的法则碎片", 800),
            ("虚无之力", ItemType.材料, "虚无中诞生的力量", 600),
            ("古塔钥匙", ItemType.其他, "开启古塔的钥匙", 1),
            ("虚空令", ItemType.其他, "进入虚空秘境的令牌", 1),
            ("云霄令", ItemType.其他, "云霄宫的通行令", 1),
            ("筑基丹", ItemType.丹药, "助人筑基的丹药", 100),
            ("金丹", ItemType.丹药, "凝聚金丹的神丹", 300),
            ("破障丹", ItemType.丹药, "突破瓶颈的丹药", 80),
            ("回血丹", ItemType.丹药, "恢复生命力的丹药", 25),
            ("回蓝丹", ItemType.丹药, "恢复法力的丹药", 25),
        ]
        
        for name, item_type, desc, value in items_data:
            self.items[name] = Item(name, item_type, desc, value)
    
    def _load_map_config(self):
        """加载地图配置"""
        config_file = self.data_dir / "map.ini"
        if not config_file.exists():
            return
        
        import configparser
        config = configparser.ConfigParser(interpolation=None)
        config.read(config_file, encoding='utf-8')
        
        for section_name in config.sections():
            if section_name.startswith("区域_"):
                area_name = section_name[3:]  # 去掉"区域_"前缀
                section = config[section_name]
                
                # 解析相邻区域
                adjacent_str = section.get('相邻区域', '')
                adjacent_areas = [area.strip() for area in adjacent_str.split(',') if area.strip()]
                
                # 解析境界限制
                realm_str = section.get('境界限制', '无')
                realm_requirement = Realm.from_string(realm_str)
                
                # 解析解锁道具
                unlock_item = section.get('解锁道具', None)
                
                # 解析资源库
                resources = {}
                resources_str = section.get('资源库', '')
                if resources_str:
                    for resource in resources_str.split(','):
                        resource = resource.strip()
                        if '(' in resource and ')' in resource:
                            name = resource[:resource.find('(')]
                            prob_str = resource[resource.find('(')+1:resource.find(')')]
                            prob = float(prob_str.rstrip('%')) / 100
                            resources[name] = prob
                
                # 解析随机事件
                events = {}
                events_str = section.get('随机事件', '')
                if events_str:
                    for event in events_str.split(','):
                        event = event.strip()
                        if '(' in event and ')' in event:
                            name = event[:event.find('(')]
                            prob_str = event[event.find('(')+1:event.find(')')]
                            prob = float(prob_str.rstrip('%')) / 100
                            events[name] = prob
                
                self.areas[area_name] = AreaInfo(
                    name=area_name,
                    adjacent_areas=adjacent_areas,
                    realm_requirement=realm_requirement,
                    unlock_item=unlock_item,
                    resources=resources,
                    random_events=events
                )
    
    def _init_events(self):
        """初始化游戏事件"""
        events_data = [
            ("管理员巡查", "管理员正在巡查，你小心翼翼地避开了", {"exp": 5}),
            ("灵宠出现", "一只小灵狐出现在你面前，似乎很亲近你", {"exp": 10, "item": "灵狐毛"}),
            ("灵脉波动", "感受到灵脉的波动，你的修为有所精进", {"exp": 20}),
            ("限号提示", "系统提示：当前在线人数过多，请稍后再试", {"message": "彩蛋事件触发！"}),
            ("灵蝶围攻", "一群灵蝶将你包围，你需要小心应对", {"battle": "灵蝶群"}),
            ("同道求助", "遇到一位同道中人求助，你选择伸出援手", {"exp": 15, "item": "感谢信"}),
        ]
        
        for name, desc, effects in events_data:
            self.events[name] = GameEvent(name, desc, 0.1, effects)
    
    def get_player(self, user_id: str, name: str = None) -> Player:
        """获取或创建玩家"""
        if user_id not in self.players:
            self.players[user_id] = Player(user_id, name or f"修仙者{user_id[-4:]}")
        return self.players[user_id]
    
    def save_player_data(self):
        """保存玩家数据"""
        data_file = self.data_dir / "players.json"
        players_data = {}
        for user_id, player in self.players.items():
            players_data[user_id] = {
                "name": player.name,
                "realm": player.realm.name,
                "exp": player.exp,
                "hp": player.hp,
                "max_hp": player.max_hp,
                "mp": player.mp,
                "max_mp": player.max_mp,
                "current_area": player.current_area,
                "inventory": player.inventory,
                "unlocked_areas": player.unlocked_areas
            }
        
        with open(data_file, 'w', encoding='utf-8') as f:
            json.dump(players_data, f, ensure_ascii=False, indent=2)
    
    def load_player_data(self):
        """加载玩家数据"""
        data_file = self.data_dir / "players.json"
        if not data_file.exists():
            return
        
        try:
            with open(data_file, 'r', encoding='utf-8') as f:
                players_data = json.load(f)
            
            for user_id, data in players_data.items():
                player = Player(
                    user_id=user_id,
                    name=data["name"],
                    realm=Realm.from_string(data["realm"]),
                    exp=data["exp"],
                    hp=data["hp"],
                    max_hp=data["max_hp"],
                    mp=data["mp"],
                    max_mp=data["max_mp"],
                    current_area=data["current_area"],
                    inventory=data["inventory"],
                    unlocked_areas=data["unlocked_areas"]
                )
                self.players[user_id] = player
        except Exception as e:
            print(f"加载玩家数据失败: {e}")
    
    def has_player(self, user_id: str) -> bool:
        """检查是否已有该用户的角色"""
        return user_id in self.players
    
    def _init_monsters(self):
        """初始化怪物数据"""
        # 按区域和境界等级配置怪物
        self.monsters = {
            "清河镇": [
                Monster("野狗", 1, 30, 8, 2, 5, {"低阶灵石": 0.1}),
                Monster("山贼", 2, 50, 12, 3, 8, {"破损妖丹": 0.15, "低阶灵石": 0.2}),
            ],
            "青城": [
                Monster("练气妖兽", 3, 80, 15, 5, 12, {"低阶灵石": 0.3, "破损妖丹": 0.2}),
                Monster("邪修", 4, 100, 18, 6, 15, {"中阶灵石": 0.1, "完整妖丹": 0.1}),
            ],
            "灵蝶谷": [
                Monster("灵蝶", 5, 120, 20, 8, 20, {"蝶翼令牌": 0.05, "中阶灵石": 0.2}),
                Monster("筑基妖兽", 6, 150, 25, 10, 25, {"完整妖丹": 0.3, "炼丹手册": 0.05}),
            ],
            "鹅城": [
                Monster("江湖恶霸", 4, 90, 16, 7, 18, {"精铁剑": 0.1, "低阶灵石": 0.25}),
                Monster("邪道修士", 5, 110, 22, 8, 22, {"中阶灵石": 0.15, "破损妖丹": 0.2}),
            ],
            "灵泉洞府": [
                Monster("洞府守护兽", 7, 180, 28, 12, 30, {"灵泉甘露": 0.2, "洞府法器": 0.1}),
                Monster("筑基后期妖兽", 8, 200, 32, 14, 35, {"灵石精华": 0.15, "中阶灵石": 0.3}),
            ],
            "天机阁": [
                Monster("天机傀儡", 10, 300, 40, 18, 50, {"高阶功法": 0.05, "天机令": 0.1}),
                Monster("金丹妖兽", 12, 400, 50, 22, 60, {"预言卷轴": 0.1, "高阶灵石": 0.2}),
            ],
            "古塔遗迹": [
                Monster("古塔守护者", 15, 500, 60, 25, 80, {"上古符文": 0.2, "古塔法宝": 0.1}),
                Monster("上古怨灵", 18, 600, 70, 30, 100, {"空间灵石": 0.15, "古塔钥匙": 0.02}),
            ],
            "仙市坊": [
                Monster("黑市杀手", 12, 350, 45, 20, 65, {"仙市灵石": 0.2, "坊市法器": 0.1}),
                Monster("商贾护卫", 14, 420, 55, 24, 75, {"商贾秘闻": 0.15, "中阶灵石": 0.3}),
            ],
            "藏书楼": [
                Monster("书灵", 16, 480, 58, 28, 85, {"古籍秘典": 0.2, "修仙心得": 0.15}),
                Monster("知识守护者", 20, 650, 75, 35, 120, {"历史真相": 0.1, "藏书楼通行证": 0.02}),
            ],
            "虚空秘境": [
                Monster("虚空魔兽", 25, 800, 90, 40, 150, {"虚空精华": 0.2, "虚空法宝": 0.1}),
                Monster("空间裂隙怪", 28, 1000, 110, 45, 180, {"空间碎片": 0.15, "虚空令": 0.02}),
            ],
            "云霄宫": [
                Monster("云霄仙兵", 22, 700, 80, 38, 140, {"云霄仙石": 0.25, "九天符箓": 0.15}),
                Monster("仙宫守卫", 26, 900, 100, 42, 170, {"仙宫秘宝": 0.1, "云霄令": 0.02}),
            ],
            "禁书区": [
                Monster("禁忌守护者", 30, 1200, 120, 50, 200, {"禁忌知识": 0.2, "上古秘法": 0.15}),
                Monster("真理化身", 35, 1500, 150, 60, 250, {"真理碎片": 0.1, "禁书钥匙": 0.02}),
            ],
            "混沌虚空": [
                Monster("混沌魔神", 40, 2000, 180, 70, 300, {"混沌精华": 0.2, "创世法则": 0.1}),
                Monster("虚无之兽", 45, 2500, 220, 80, 400, {"虚无之力": 0.15, "混沌精华": 0.25}),
            ],
            "九天云海": [
                Monster("九天神兽", 38, 1800, 160, 65, 280, {"九天灵果": 0.2, "云海仙草": 0.18}),
                Monster("风灵", 42, 2200, 200, 75, 350, {"风灵精华": 0.15, "九天符箓": 0.1}),
            ],
            "时光殿": [
                Monster("时光守护者", 50, 3000, 250, 90, 500, {"时光水晶": 0.2, "岁月回响": 0.15}),
                Monster("时间之主", 55, 4000, 300, 100, 600, {"未来预言": 0.1, "时光水晶": 0.3}),
            ],
        }